﻿#ifndef CUSTOM_LIT_PASS_INCLUDED
#define CUSTOM_LIT_PASS_INCLUDED

#include "../ShaderLibrary/Surface.hlsl"
#include "../ShaderLibrary/Shadows.hlsl"
#include "../ShaderLibrary/Light.hlsl"
#include "../ShaderLibrary/BRDF.hlsl"
#include "../ShaderLibrary/GI.hlsl"
#include "../ShaderLibrary/IBL.hlsl"
#include "../ShaderLibrary/Lighting.hlsl"
#include "Util.hlsl"

struct Attributes {
	float3 positionOS : POSITION;
	float3 normalOS : NORMAL;
	float4 tangentOS : TANGENT;
	float2 baseUV : TEXCOORD0;
#if defined(_WINDGRASS)||defined(_VEGETATION_TREE)
	float4 color : COLOR;
#endif
	GI_ATTRIBUTE_DATA
	UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct Varyings {
	float4 positionCS_SS : SV_POSITION;
	float3 positionWS : VAR_POSITION;
	float3 normalWS : VAR_NORMAL;
	#if defined(_NORMAL_MAP)
		float4 tangentWS : VAR_TANGENT;
	#endif
	float2 baseUV : VAR_BASE_UV;
	#if defined(_DETAIL_MAP)
		float2 detailUV : VAR_DETAIL_UV;
	#endif
	
	#if defined(_SKIN)
		float2 brdfUV : VAR_BRDF_UV;
		float2 sssUV : VAR_SSS_UV;
	#endif
	
	#if defined(_VEGETATION_TREE)
		half occ : VAR_OCC_VALUE;
		float emiCol : VAR_EMICOL_VALUE;
	#endif

	GI_VARYINGS_DATA
	UNITY_VERTEX_INPUT_INSTANCE_ID
};

Varyings LitPassVertex (Attributes input) {
	Varyings output;
	UNITY_SETUP_INSTANCE_ID(input);
	UNITY_TRANSFER_INSTANCE_ID(input, output);
	TRANSFER_GI_DATA(input, output);

#if defined(_VEGETATION_TREE)
	#ifdef USE_VERTEXANIM
		 //Wave 1
		float3 winDirection = float3(1, 0.5, 0.5);
		input.positionOS.xyz += normalize(winDirection + input.normalOS) * input.color.g * sin(((input.color.b * 3.141592654) + _Time)) * 0.08;// * _GlobalWindAmount;
		input.positionOS.x += sin((input.positionOS.y + _Time * GetVertAnim_Speed()) * GetVertAnim_Frequency()) * GetVertAnim_Offset() * input.color.a;// * _GlobalWindAmount;
	#endif
	output.occ = lerp(1, (1 - input.color.r), GetOccAmount());
	output.emiCol = input.color.g * GetEmissionVal();
#endif

	output.positionWS = TransformObjectToWorld(input.positionOS);

#if defined(_WINDGRASS)
	output.positionWS = WindGrassWave(float4(output.positionWS, 1.0), input.color.a, GetWindEdgeFlutterFreqScale(), GetWind(),
		0, float4(0, 0, 0, 0), GetColliderRadius(), GetPlayerForce(), GetForceY());
#endif

	output.positionCS_SS = TransformWorldToHClip(output.positionWS);
	output.normalWS = TransformObjectToWorldNormal(input.normalOS);
	#if defined(_NORMAL_MAP)
		output.tangentWS = float4(
			TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w
		);
	#endif
	output.baseUV = TransformBaseUV(input.baseUV);
	#if defined(_DETAIL_MAP)
		output.detailUV = TransformDetailUV(input.baseUV);
	#endif
	
	#if defined(_SKIN)
		output.brdfUV = TransformBRDFUV(input.baseUV);
		output.sssUV = TransformSSSUV(input.baseUV);
	#endif
	
	return output;
}

float4 LitPassFragment (Varyings input) : SV_TARGET {
	UNITY_SETUP_INSTANCE_ID(input);
	InputConfig config = GetInputConfig(input.positionCS_SS, input.baseUV);
	ClipLOD(config.fragment, unity_LODFade.x);
	
	#if defined(_MASK_MAP)
		config.useMask = true;
	#endif
	#if defined(_DETAIL_MAP)
		config.detailUV = input.detailUV;
		config.useDetail = true;
	#endif
	
	float4 base = GetBase(config);
	#if defined(_CLIPPING)
		clip(base.a - GetCutoff(config));
	#endif
	
	Surface surface;
	surface.position = input.positionWS;
	#if defined(_NORMAL_MAP)
		surface.normal = NormalTangentToWorld(
			GetNormalTS(config), input.normalWS, input.tangentWS
		);
		surface.interpolatedNormal = input.normalWS;
	#else
		surface.normal = normalize(input.normalWS);
		surface.interpolatedNormal = surface.normal;
	#endif
	surface.viewDirection = normalize(_WorldSpaceCameraPos - input.positionWS);
	surface.depth = -TransformWorldToView(input.positionWS).z;
	#if defined(_VEGETATION_TREE)
		base.rgb = base.rgb * input.occ;
		base.rgb += base.rgb * input.emiCol;
	#endif
	surface.color = base.rgb;
	surface.alpha = base.a;
	surface.metallic = GetMetallic(config);
	surface.occlusion = GetOcclusion(config);
	surface.smoothness = GetSmoothness(config);
	surface.fresnelStrength = GetFresnel(config);
	surface.dither = InterleavedGradientNoise(config.fragment.positionSS, 0);
	surface.renderingLayerMask = asuint(unity_RenderingLayer.x);
	#if _SKIN
		surface.curvature = GetCurvature(config);
		surface.thickness = GetThickness(config);
		surface.thicknessScale = GetThicknessScale(config);	
		surface.subColor = GetSubColor();
		surface.power = GetPower();
		surface.distortion = GetDistortion();
	#elif _FABRIC
		surface.fabricScatterColor = GetFabricScatterColor();
		surface.fabricScatterScale = GetScatterScale();	
	#endif

	#if defined(_IBL)&&defined(_IBL_RP_ON)
		surface.irradianceScale = GetIrradianceScale();
		surface.specularReflectScale = GetSpecularReflectScale();
	#endif

	#if defined(_PREMULTIPLY_ALPHA)
		BRDF brdf = GetBRDF(surface, true);
	#else
		BRDF brdf = GetBRDF(surface);
	#endif

	#if defined(_IBL)&&defined(_IBL_RP_ON)
		IBL ibl = GetIBL(surface, brdf);
		float3 color = GetLighting(surface, brdf, ibl);
	#else
		GI gi = GetGI(GI_FRAGMENT_DATA(input), surface, brdf);
		float3 color = GetLighting(surface, brdf, gi);
	#endif

	color += GetEmission(config);
	return float4(color, GetFinalAlpha(surface.alpha));
}

#endif